#!/bin/bash

# 服务健康检查脚本
# 检查Web、MySQL、Redis等服务状态，异常自动重启或通知

# 配置参数
CHECK_INTERVAL=30       # 检查间隔(秒)
ALERT_EMAIL="admin@example.com"  # 告警接收邮箱
LOG_FILE="/var/log/service_health_check.log"  # 日志文件

# 服务配置
WEB_SERVICE="nginx"     # Web服务名称
WEB_PORT=80             # Web服务端口
WEB_URL="http://localhost"  # 用于健康检查的URL

MYSQL_SERVICE="mysql"   # MySQL服务名称
MYSQL_PORT=3306         # MySQL端口
MYSQL_USER="healthcheck"  # 检查用MySQL用户
MYSQL_PASS="checkpass"  # 检查用MySQL密码

REDIS_SERVICE="redis-server"  # Redis服务名称
REDIS_PORT=6379         # Redis端口

# 日志记录函数
log() {
    local message="$1"
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $message" >> "$LOG_FILE"
    echo "$message"
}

# 发送告警邮件
send_alert() {
    local service="$1"
    local status="$2"
    local subject="服务异常告警 - $service ($(hostname))"
    local message="服务 $service 出现异常: $status\n时间: $(date)\n主机: $(hostname)"
    echo "$message" | mail -s "$subject" "$ALERT_EMAIL"
    log "已发送告警邮件: $service 异常"
}

# 检查并重启服务
check_and_restart() {
    local service="$1"
    local port="$2"
    local check_command="$3"
    
    log "检查服务: $service (端口: $port)"
    
    # 检查进程是否存在
    if ! pgrep -x "$service" > /dev/null; then
        log "$service 进程未运行，尝试重启..."
        systemctl start "$service"
        sleep 5
        
        # 检查重启是否成功
        if pgrep -x "$service" > /dev/null; then
            log "$service 重启成功"
            send_alert "$service" "进程已崩溃，已成功重启"
        else
            log "$service 重启失败"
            send_alert "$service" "进程已崩溃，重启失败，请手动处理"
        fi
        return
    fi
    
    # 检查端口是否监听
    if ! netstat -tuln | grep -q ":$port "; then
        log "$service 端口 $port 未监听，尝试重启..."
        systemctl restart "$service"
        sleep 5
        
        if netstat -tuln | grep -q ":$port "; then
            log "$service 重启成功，端口已监听"
            send_alert "$service" "端口未监听，已成功重启"
        else
            log "$service 重启失败，端口仍未监听"
            send_alert "$service" "端口未监听，重启失败，请手动处理"
        fi
        return
    fi
    
    # 执行自定义检查命令（如适用）
    if [ -n "$check_command" ]; then
        if ! eval "$check_command"; then
            log "$service 自定义检查失败，尝试重启..."
            systemctl restart "$service"
            sleep 5
            
            if eval "$check_command"; then
                log "$service 重启成功，自定义检查通过"
                send_alert "$service" "自定义检查失败，已成功重启"
            else
                log "$service 重启失败，自定义检查仍未通过"
                send_alert "$service" "自定义检查失败，重启失败，请手动处理"
            fi
            return
        fi
    fi
    
    log "$service 运行正常"
}

# 主循环
while true; do
    log "===== 开始服务健康检查 ====="
    
    # 检查Web服务
    web_check_command="curl -s --head $WEB_URL | grep -q '200 OK'"
    check_and_restart "$WEB_SERVICE" "$WEB_PORT" "$web_check_command"
    
    # 检查MySQL服务
    mysql_check_command="mysql -u $MYSQL_USER -p$MYSQL_PASS -e 'SELECT 1' > /dev/null 2>&1"
    check_and_restart "$MYSQL_SERVICE" "$MYSQL_PORT" "$mysql_check_command"
    
    # 检查Redis服务
    redis_check_command="redis-cli -p $REDIS_PORT ping | grep -q 'PONG'"
    check_and_restart "$REDIS_SERVICE" "$REDIS_PORT" "$redis_check_command"
    
    log "===== 服务健康检查完成 ====="
    sleep $CHECK_INTERVAL
done
